package cn.xy.ymcc.service.impl;

import cn.xy.ymcc.constants.CommonConstants;
import cn.xy.ymcc.constants.YmccError;
import cn.xy.ymcc.domain.Login;
import cn.xy.ymcc.domain.User;
import cn.xy.ymcc.domain.UserAccount;
import cn.xy.ymcc.domain.UserBaseInfo;
import cn.xy.ymcc.dto.RedisRegisterDto;
import cn.xy.ymcc.dto.RegisterDto;
import cn.xy.ymcc.feign.LoginFeignClient;
import cn.xy.ymcc.mapper.UserMapper;
import cn.xy.ymcc.result.JSONResult;
import cn.xy.ymcc.service.IUserAccountService;
import cn.xy.ymcc.service.IUserBaseInfoService;
import cn.xy.ymcc.service.IUserService;
import cn.xy.ymcc.util.AssertUtil;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;

/**
 * <p>
 * 会员登录账号 服务实现类
 * </p>
 *
 * @author xy.cao
 * @since 2022-07-15
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    @Autowired
    private LoginFeignClient loginFeignClient;

    @Autowired
    private IUserBaseInfoService userBaseInfoService;

    @Autowired
    private IUserAccountService userAccountService;

    /**
     * 手机号注册
     * @param dto
     */
    @Override
    @GlobalTransactional
    public void register(RegisterDto dto) {
        //判断验证码是否为null。
        String key = String.format(CommonConstants.REGISTER_PHONE_PREFIX,dto.getMobile());
        Object o = redisTemplate.opsForValue().get(key);
        AssertUtil.isNotNull(o, YmccError.USER_SMS_EMPTY.getMessage());
        //强转格式，与注册验证码格式相同
        RedisRegisterDto registerDto = (RedisRegisterDto) o;
        //判断是否相等
        AssertUtil.isEquals(registerDto.getSmsCode(),dto.getSmsCode(),YmccError.USER_SMSCODE_NOTEQUALS.getMessage());

        User user = selectUserByPhone(dto.getMobile());
        //防御性编程
        AssertUtil.isNull(user,YmccError.USER_EXISTS.getMessage());

        //保存t_login
        JSONResult jsonResult = saveLogin(dto);
        AssertUtil.isTrue(jsonResult.isSuccess(),jsonResult.getMessage()); //判断调用微服务uaa进行登录信息保存是否成功
        AssertUtil.isNotNull(jsonResult.getData(),"登录信息保存失败"); //因为调用登录心机接口后会返回自增id到data中，所以这里判断一波

        //保存t_user表
        Long loginId = Long.valueOf(jsonResult.getData().toString());  //获取loginId
        user = saveUser(loginId, dto.getMobile()); //保存user表
        //判断是否为Null
        AssertUtil.isNotNull(user.getId(),"用户保存失败");

        //保存t_user_base_info
        initUserInfo(user.getId(),dto.getRegChannel());

        //保存t_user_account
        initUserAccount(user.getId());

    }

    /**
     * 保存user_account表
     */
    private void initUserAccount(Long userId) {
        UserAccount userAccount = new UserAccount();
        userAccount.setCreateTime(new Date().getTime());
        userAccount.setId(userId);
        userAccountService.insert(userAccount);
    }

    /**
     * 保存userinfo表
     * @param userId
     * @param regChannel
     */

    private void initUserInfo(Long userId ,Integer regChannel) {
        UserBaseInfo userBaseInfo = new UserBaseInfo();
        userBaseInfo.setId(userId);
        userBaseInfo.setCreateTime(new Date().getTime());
        userBaseInfo.setRegChannel(regChannel);
        userBaseInfoService.insert(userBaseInfo);

    }

    /**
     * 保存t_user表数据
     * @param loginId
     * @param mobile
     * @return
     */
    private User saveUser(Long loginId,String mobile) {
        User user = new User();
        user.setLoginId(loginId);
        user.setPhone(mobile);
        user.setNickName(mobile);
        user.setCreateTime(new Date().getTime());
        insert(user);
        return user;
    }

    /**
     * 保存t_login数据
     * @param dto
     * @return
     */
    private JSONResult saveLogin(RegisterDto dto) {
        Login login = new Login();
        login.setUsername(dto.getMobile());
        login.setPassword(dto.getPassword());

        return loginFeignClient.save(login);
    }

    /**
     * mubatisplus自带的sql编写
     * @param mobile
     * @return
     */
    private User selectUserByPhone(String mobile) {
        Wrapper<User> tWrapper = new EntityWrapper<>();
        tWrapper.eq("phone",mobile);
        return selectOne(tWrapper);
    }

}
